// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraAbilitySet.h"

#include "AbilitySystem/Abilities/LyraGameplayAbility.h"
#include "LyraAbilitySystemComponent.h"
#include "LyraLogChannels.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraAbilitySet)  // UE5内联生成代码包含

// 添加有效的能力规格句柄到数组
void FLyraAbilitySet_GrantedHandles::AddAbilitySpecHandle(const FGameplayAbilitySpecHandle& Handle)
{
    if (Handle.IsValid())  // 检查句柄是否有效
    {
        AbilitySpecHandles.Add(Handle);  // 添加到数组
    }
}

// 添加有效的游戏效果句柄到数组
void FLyraAbilitySet_GrantedHandles::AddGameplayEffectHandle(const FActiveGameplayEffectHandle& Handle)
{
    if (Handle.IsValid())  // 检查句柄是否有效
    {
        GameplayEffectHandles.Add(Handle);  // 添加到数组
    }
}

// 添加属性集到数组
void FLyraAbilitySet_GrantedHandles::AddAttributeSet(UAttributeSet* Set)
{
    GrantedAttributeSets.Add(Set);  // 添加到数组
}

// 从能力系统组件中移除所有已授予的内容
void FLyraAbilitySet_GrantedHandles::TakeFromAbilitySystem(ULyraAbilitySystemComponent* LyraASC)
{
    check(LyraASC);  // 确保LyraASC不为空

    if (!LyraASC->IsOwnerActorAuthoritative())  // 检查是否为权威端
    {
        // 必须是权威端才能授予或移除能力集
        return;
    }

    // 移除所有已授予的能力
    for (const FGameplayAbilitySpecHandle& Handle : AbilitySpecHandles)
    {
        if (Handle.IsValid())  // 检查句柄是否有效
        {
            LyraASC->ClearAbility(Handle);  // 清除能力
        }
    }

    // 移除所有已授予的游戏效果
    for (const FActiveGameplayEffectHandle& Handle : GameplayEffectHandles)
    {
        if (Handle.IsValid())  // 检查句柄是否有效
        {
            LyraASC->RemoveActiveGameplayEffect(Handle);  // 移除活动游戏效果
        }
    }

    // 移除所有已授予的属性集
    for (UAttributeSet* Set : GrantedAttributeSets)
    {
        LyraASC->RemoveSpawnedAttribute(Set);  // 移除生成的属性集
    }

    // 重置所有数组
    AbilitySpecHandles.Reset();
    GameplayEffectHandles.Reset();
    GrantedAttributeSets.Reset();
}

// 构造函数
ULyraAbilitySet::ULyraAbilitySet(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)  // 调用父类构造函数
{
}

// 将能力集授予指定的能力系统组件
void ULyraAbilitySet::GiveToAbilitySystem(ULyraAbilitySystemComponent* LyraASC, FLyraAbilitySet_GrantedHandles* OutGrantedHandles, UObject* SourceObject) const
{
    check(LyraASC);  // 确保LyraASC不为空

    if (!LyraASC->IsOwnerActorAuthoritative())  // 检查是否为权威端
    {
        // 必须是权威端才能授予或移除能力集
        return;
    }

    // 授予游戏能力
    for (int32 AbilityIndex = 0; AbilityIndex < GrantedGameplayAbilities.Num(); ++AbilityIndex)
    {
        const FLyraAbilitySet_GameplayAbility& AbilityToGrant = GrantedGameplayAbilities[AbilityIndex];

        if (!IsValid(AbilityToGrant.Ability))  // 检查能力是否有效
        {
            UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayAbilities[%d] on ability set [%s] is not valid."), AbilityIndex, *GetNameSafe(this));
            continue;  // 跳过无效能力
        }

        // 获取能力的默认对象
        ULyraGameplayAbility* AbilityCDO = AbilityToGrant.Ability->GetDefaultObject<ULyraGameplayAbility>();

        // 创建能力规格
        FGameplayAbilitySpec AbilitySpec(AbilityCDO, AbilityToGrant.AbilityLevel);
        AbilitySpec.SourceObject = SourceObject;  // 设置源对象
        AbilitySpec.DynamicAbilityTags.AddTag(AbilityToGrant.InputTag);  // 添加输入标签

        // 授予能力并获取句柄
        const FGameplayAbilitySpecHandle AbilitySpecHandle = LyraASC->GiveAbility(AbilitySpec);

        if (OutGrantedHandles)  // 如果提供了输出句柄
        {
            OutGrantedHandles->AddAbilitySpecHandle(AbilitySpecHandle);  // 添加能力句柄
        }
    }

    // 授予游戏效果
    for (int32 EffectIndex = 0; EffectIndex < GrantedGameplayEffects.Num(); ++EffectIndex)
    {
        const FLyraAbilitySet_GameplayEffect& EffectToGrant = GrantedGameplayEffects[EffectIndex];

        if (!IsValid(EffectToGrant.GameplayEffect))  // 检查效果是否有效
        {
            UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedGameplayEffects[%d] on ability set [%s] is not valid"), EffectIndex, *GetNameSafe(this));
            continue;  // 跳过无效效果
        }

        // 获取游戏效果的默认对象
        const UGameplayEffect* GameplayEffect = EffectToGrant.GameplayEffect->GetDefaultObject<UGameplayEffect>();
        // 应用游戏效果到自身
        const FActiveGameplayEffectHandle GameplayEffectHandle = LyraASC->ApplyGameplayEffectToSelf(GameplayEffect, EffectToGrant.EffectLevel, LyraASC->MakeEffectContext());

        if (OutGrantedHandles)  // 如果提供了输出句柄
        {
            OutGrantedHandles->AddGameplayEffectHandle(GameplayEffectHandle);  // 添加效果句柄
        }
    }

    // 授予属性集
    for (int32 SetIndex = 0; SetIndex < GrantedAttributes.Num(); ++SetIndex)
    {
        const FLyraAbilitySet_AttributeSet& SetToGrant = GrantedAttributes[SetIndex];

        if (!IsValid(SetToGrant.AttributeSet))  // 检查属性集是否有效
        {
            UE_LOG(LogLyraAbilitySystem, Error, TEXT("GrantedAttributes[%d] on ability set [%s] is not valid"), SetIndex, *GetNameSafe(this));
            continue;  // 跳过无效属性集
        }

        // 创建新的属性集对象
        UAttributeSet* NewSet = NewObject<UAttributeSet>(LyraASC->GetOwner(), SetToGrant.AttributeSet);
        // 添加属性集子对象
        LyraASC->AddAttributeSetSubobject(NewSet);

        if (OutGrantedHandles)  // 如果提供了输出句柄
        {
            OutGrantedHandles->AddAttributeSet(NewSet);  // 添加属性集
        }
    }
}